# import jusmargui
from PySide2.QtWidgets import (
    QApplication,
    QWidget,
    QTableWidgetItem,
    QTableWidget,
    QHeaderView,
    QAbstractItemView,
    QVBoxLayout,
    QTabWidget,
    QGroupBox,
    QLabel,
    QLineEdit,
    QHBoxLayout,
    QGridLayout,
    QComboBox,
    QPushButton,
    QListWidget,
    QDialog,
    QButtonGroup,
    QRadioButton,
    QCheckBox,
    QListWidgetItem,
    QMessageBox,
    QGraphicsColorizeEffect,
    QFileDialog,
    QSpacerItem,
    QSizePolicy,
)

from PySide2.QtCore import Qt, Signal
from PySide2.QtGui import QPixmap, QDoubleValidator, QIntValidator, QImage, QColor
import sys
import csv
import os
import json
import subprocess
import copy
from gui.controls import envs
from .. import message_box as MBox
from .. import config as Config
from ..utils import Utils
from ..dlg_model_params import DlgModeResetCls
from ..params_table import ParamsTable, OnlyOneRowTable
from ..custom_widget import SelectBox
import csv

class CustomTableWidgetItem(QTableWidgetItem):
    def __init__(self, text):
        super().__init__(text)
        self.setTextAlignment(Qt.AlignCenter)  # 文本居中对齐


# class SingelTable(ParamsTable):
#     def __init__(self, rows=0, columns=2, parent=None):
#         super(SingelTable, self).__init__(rows=rows, columns=columns, parent=parent)
#         self.setContextMenuPolicy(Qt.NoContextMenu)  # 禁用右键菜单


def export_tables_to_single_csv(tables: list, output_path: str = None) -> bool:
        """
        将多个行数相同的TableWidget合并导出为一个CSV
        
        参数:
            tables: 包含多个QTableWidget的列表
            output_path: 可选的自定义输出路径
            
        返回:
            bool: 导出是否成功
        """
        # 验证表格数据
        if not tables:
            return False
            
        row_count = tables[0].rowCount()
        if any(table.rowCount() != row_count for table in tables):
            print("错误：表格行数不一致")
            return False

        # 获取保存路径
        if not output_path:
            output_path, _ = QFileDialog.getSaveFileName(
                tables[0],  # 父窗口
                "导出CSV文件",
                "data",
                "CSV文件 (*.csv)"
            )
            if not output_path:
                return False
            if not output_path.lower().endswith('.csv'):
                output_path += '.csv'

        # 准备合并后的数据
        merged_data = []
        
        # 添加表头（合并所有表格的表头）
        headers = []
        for table in tables:
            for col in range(table.columnCount()):
                header = table.horizontalHeaderItem(col)
                headers.append(header.text() if header else f"Table{table.columnCount()}_Col{col+1}")
        merged_data.append(headers)
        
        # 添加内容（逐行合并）
        for row in range(row_count):
            row_data = []
            for table in tables:
                for col in range(table.columnCount()):
                    item = table.item(row, col)
                    row_data.append(item.text() if item else "")
            merged_data.append(row_data)
        
        # 写入文件
        try:
            with open(output_path, 'w', newline='', encoding='utf-8-sig') as f:
                writer = csv.writer(f)
                writer.writerows(merged_data)
            MBox.success(f"导出成功！")
            return True
        except Exception as e:
            MBox.warning(f"导出失败: {str(e)}")
            return False


class OnlyOneRowStringTable(OnlyOneRowTable):
    export_signal = Signal()
    def __init__(self, rows=0, columns=2, isLibrary=False, parent=None):
        super(OnlyOneRowStringTable, self).__init__(rows, columns, isLibrary, parent)
        
    def export(self):
        self.export_signal.emit()
        
        
class StringTable(ParamsTable):
    export_signal = Signal()
    def __init__(self, rows=0, columns=2, isLibrary=False, parent=None):
        super(StringTable, self).__init__(rows, columns, isLibrary, parent)
        
    def export(self):
        self.export_signal.emit()


class DlgStringer(DlgModeResetCls):
    stringer_save_signal = Signal(object)
    materialLibraryLocking_update_signal = Signal(object)
    stringedBarLibraryLocking_update_signal = Signal(object)

    def __init__(self, parent=None, params={}):
        super().__init__(parent)
        title = f"蒙皮桁条-{params.get('title')or''}"
        self.setWindowTitle(title)
        self.resize(900, 420)

        self.materialData = Utils.read_json(Config.cachePath + "materialLibrary.json")
        self.materialOptions = []
        if self.materialData:
            for key, _ in self.materialData.items():
                self.materialOptions.append({"title": key, "value": key})

        self.stringedBarData = Utils.read_json(
            Config.cachePath + "stringedBarLibrary.json"
        )
        self.stringedBarOptions = []
        if self.stringedBarData:
            for key, _ in self.stringedBarData.items():
                self.stringedBarOptions.append({"title": key, "value": key})

        self.widgetDict = {}

        layout = QVBoxLayout()
        hLayout = QHBoxLayout()
        skinGroupBox = QGroupBox("蒙皮及其他参数")
        skinLayout = QVBoxLayout()
        self.widgetDict["skin1"] = OnlyOneRowStringTable(rows=0, columns=2)
        self.widgetDict["skin1"].setHorizontalHeaderLabels(
            ["初始属性编号", "初始单元编号"]
        )
        self.widgetDict["skin1"].rowSetInt([0, 1])
        self.widgetDict["skin1"].add()
        self.widgetDict["skin1"].export_signal.connect(
            self.skin_export
        )
        # self.widgetDict["skin1"].setRowHeight(0, 30)
        self.setTableFixeHeight(self.widgetDict["skin1"])
        skinLayout.addWidget(self.widgetDict["skin1"])

        self.widgetDict["skin2"] = OnlyOneRowStringTable(rows=0, columns=2)
        self.widgetDict["skin2"].setHorizontalHeaderLabels(["蒙皮材料", "最大尺寸"])
        self.widgetDict["skin2"].rowSetSelect([0], options={"0": self.materialOptions})
        self.widgetDict["skin2"].rowSetFloat([1])
        self.widgetDict["skin2"].add()
        self.widgetDict["skin2"].export_signal.connect(
            self.skin_export
        )
        # self.widgetDict["skin2"].setRowHeight(0, 30)
        self.setTableFixeHeight(self.widgetDict["skin2"])
        skinLayout.addWidget(self.widgetDict["skin2"])

        self.widgetDict["skin3"] = OnlyOneRowStringTable(rows=0, columns=2)
        self.widgetDict["skin3"].setHorizontalHeaderLabels(["蒙皮厚度", "厚度"])
        self.widgetDict["skin3"].rowSetSelect(
            [0],
            options={
                "0": [
                    {"value": "均匀厚度", "title": "均匀厚度"},
                    {"value": "按周向设置", "title": "按周向设置"},
                ]
            },
        )
        self.widgetDict["skin3"].add()
        self.widgetDict["skin3"].select_changed_signal.connect(
            self.skin3_select_changed_signal
        )
        self.widgetDict["skin3"].rowSetFloat([1])
        self.widgetDict["skin3"].export_signal.connect(
            self.skin_export
        )
        self.setTableFixeHeight(self.widgetDict["skin3"])
        skinLayout.addWidget(self.widgetDict["skin3"])

        self.widgetDict["skin4"] = StringTable(rows=0, columns=3)
        self.widgetDict["skin4"].setHorizontalHeaderLabels(["起始", "终止", "厚度"])
        self.widgetDict["skin4"].rowSetFloat([0, 1, 2])
        self.widgetDict["skin4"].add()
        self.widgetDict["skin4"].export_signal.connect(
            self.skin_export
        )
        skinLayout.addWidget(self.widgetDict["skin4"])
        skinGroupBox.setLayout(skinLayout)

        vLayout = QVBoxLayout()
        ringFrameGroupBox = QGroupBox("轴向定位及环框")
        ringFrameLayout = QVBoxLayout()
        self.widgetDict["ringFrame"] = ParamsTable(rows=0, columns=8)
        self.widgetDict["ringFrame"].verticalHeader().setVisible(True)
        self.widgetDict["ringFrame"].setHorizontalHeaderLabels(
            ["节点号", "x坐标", "y坐标", "z坐标", "半径", "类型", "材料", "型式"]
        )
        self.widgetDict["ringFrame"].rowSetInt([0])
        self.widgetDict["ringFrame"].rowSetFloat([1, 2, 3, 4])
        self.widgetDict["ringFrame"].rowSetSelect(
            [5, 6, 7],
            {
                "5": [
                    {"value": "定位点", "title": "定位点"},
                    {"value": "环框", "title": "环框"},
                ],
                "6": self.materialOptions,
                "7": self.stringedBarOptions,
            },
        )
        self.widgetDict["ringFrame"].uniqueFlagColumn = 0
        self.widgetDict["ringFrame"].setAddIncrementing(True)
        ringFrameLayout.addWidget(self.widgetDict["ringFrame"])
        
        ringFrameGroupBox.setLayout(ringFrameLayout)
        vLayout.addWidget(ringFrameGroupBox)

        stretchLayout = QHBoxLayout()
        stringedBarGroupBox = QGroupBox("周向定位及桁条（+Y为0度）")
        stringedBarLayout = QVBoxLayout()
        self.widgetDict["stringedBar"] = ParamsTable(rows=0, columns=5)
        self.widgetDict["stringedBar"].setHorizontalHeaderLabels(
            ["周向起始角度", "周向终止角度", "桁条个数", "材料", "型式"]
        )
        self.widgetDict["stringedBar"].rowSetInt([2])
        self.widgetDict["stringedBar"].rowSetFloat([0, 1])
        self.widgetDict["stringedBar"].rowSetSelect(
            [3, 4],
            {"3": self.materialOptions, "4": self.stringedBarOptions},
        )

        stringedBarLayout.addWidget(self.widgetDict["stringedBar"])
        stringedBarGroupBox.setLayout(stringedBarLayout)
        stretchLayout.addStretch(1)
        stretchLayout.addWidget(stringedBarGroupBox, 5)
        stretchLayout.addStretch(1)
        vLayout.addLayout(stretchLayout)

        hLayout.addWidget(skinGroupBox, 1)
        hLayout.addLayout(vLayout, 3)
        layout.addLayout(hLayout)

        btnLayout = QHBoxLayout()
        cancelBtn = QPushButton("取消")
        okBtn = QPushButton("确定")
        saveBtn = QPushButton("保存")

        btnLayout.setAlignment(Qt.AlignCenter)

        btnLayout.addWidget(saveBtn)
        btnLayout.addWidget(okBtn)
        btnLayout.addWidget(cancelBtn)
        layout.addStretch(1)
        layout.addLayout(btnLayout)

        saveBtn.clicked.connect(self.on_saveBtn_clicked)
        okBtn.clicked.connect(self.on_okBtn_clicked)
        cancelBtn.clicked.connect(self.close)

        self.setLayout(layout)

        data = {}
        if Config.isLocation:
            self.cacheFile = Config.cachePath + "stringer.json"
            data = Utils.read_json(self.cacheFile)
        else:
            data = params.get("data") or {}
        self.updateUI(data)
        Utils.handleTableNoEdit(
            data=data.get("ringFrame"), table=self.widgetDict["ringFrame"]
        )

        self.lastMaterials = (
            Utils.getTableLibrarysName(data=data.get("ringFrame"), column=6)
            | Utils.getTableLibrarysName(data=data.get("stringedBar"), column=3)
            | Utils.getTableLibrarysName(data=data.get("skin2"), column=0)
        )
        self.lastStringedBars = Utils.getTableLibrarysName(
            data=data.get("ringFrame"), column=7
        ) | Utils.getTableLibrarysName(data=data.get("stringedBar"), column=4)

        envs.ipimas_changeStringedBar = (
            lambda library, *args, **kwargs: self.libraryChangeStringedBar(
                library, *args, **kwargs
            )
        )
        envs.ipimas_changeMaterial = (
            lambda library, *args, **kwargs: self.libraryChangeMaterial(
                library, *args, **kwargs
            )
        )

    def libraryChangeMaterial(self, library):
        if self.isVisible():
            self.materialData = library

    def libraryChangeStringedBar(self, library):
        if self.isVisible():
            self.stringedBarData = library

    def getDataDict(self):
        dict = {}
        ringFrameData = self.widgetDict["ringFrame"].getTableListFirstNoNull()
        if isinstance(ringFrameData, int):
            MBox.warning(f"轴向定位及环框 第{ringFrameData}行节点号不可为空!")
            return False
        if isinstance(ringFrameData, str):
            MBox.warning(f"轴向定位及环框 第{ringFrameData}行节点号已存在!")
            return False
        ringFrame = sorted(ringFrameData, key=lambda x: x[0])
        stringedBar = self.widgetDict["stringedBar"].getTableData()
        grid_set = []
        grid_ring = []
        for row, item in enumerate(ringFrame):
            if item[5] == "环框":
                temp = item[:5] + item[6:]
                grid_ring.append(temp)
            elif item[5] == "定位点":
                temp = item[:5] + item[6:]
                grid_set.append(temp)
            elif not item[5]:
                MBox.warning(f"轴向定位及环框 第{row+1}行类型不可为空!")
                return False

        dict["grid_set"] = Utils.filter_dict_list(grid_set)
        dict["grid_ring"] = Utils.filter_dict_list(grid_ring)
        dict["rib_r"] = Utils.filter_dict_list(stringedBar)
        dict["type"] = "shell_bar"

        skin1 = self.widgetDict["skin1"].getTableData()
        skin2 = self.widgetDict["skin2"].getTableData()
        skin3 = self.widgetDict["skin3"].getTableData()
        if len(skin1) > 0 and len(skin1[0]) > 0:
            dict["prop_start"] = skin1[0][0]
            dict["element_start"] = skin1[0][1]
        if len(skin2) > 0 and len(skin2[0]) > 0:
            dict["shell_material"] = skin2[0][0]
            dict["shell_len"] = skin2[0][1]
        if len(skin3) > 0 and len(skin3[0]) > 0:
            if skin3[0][0] == "均匀厚度":
                dict["shell_thick"] = skin3[0][1]
                dict["shell_thick_equal"] = True
            elif skin3[0][0] == "按周向设置":
                thick = Utils.filter_dict_list(self.widgetDict["skin4"].getTableData())
                dict["shell_thick"] = thick
                dict["shell_thick_equal"] = False
        return dict
    
    def on_exportStringedBar_clicked(self):
        Utils.export_to_csv(self.widgetDict["stringedBar"])
        
    def on_exportRingFrame_clicked(self):
        Utils.export_to_csv(self.widgetDict["ringFrame"])

    def on_okBtn_clicked(self):
        dict = self.getDataDict()
        if dict == False:
            return

        filterDict = Utils.filterDictEmptyProperty(dict)

        self.cacheFile = Config.cachePath + "stringer.json"
        Utils.write_json(self.cacheFile, filterDict)

        if Config.isLocation:
            Utils.write_json(self.cacheFile, dict)
        self.close()
        if Config.useLibraryLocking:
            materialLibrary = Utils.updateLockingLibrary(
                dataList=[
                    [dict["ringFrame"], 6],
                    [dict["stringedBar"], 3],
                    [dict["skin2"], 0],
                ],
                lastSelects=self.lastMaterials,
                library=self.materialData,
                file=Config.materialTable,
            )
            stringedBarLibrary = Utils.updateLockingLibrary(
                dataList=[[dict["ringFrame"], 7], [dict["stringedBar"], 4]],
                lastSelects=self.lastStringedBars,
                library=self.stringedBarData,
                file=Config.stringedBarTable,
            )
            if materialLibrary:
                if hasattr(envs, "ipimas_changeLockMaterial"):
                    envs.ipimas_changeLockMaterial()
                self.materialLibraryLocking_update_signal.emit(materialLibrary)
            if stringedBarLibrary:
                if hasattr(envs, "ipimas_changeLockStringedBar"):
                    envs.ipimas_changeLockStringedBar()
                self.stringedBarLibraryLocking_update_signal.emit(stringedBarLibrary)
        self.stringer_save_signal.emit(filterDict)

    def on_saveBtn_clicked(self):
        dict = self.getDataDict()
        if dict == False:
            return

        filterDict = Utils.filterDictEmptyProperty(dict)

        self.cacheFile = Config.cachePath + "stringer.json"
        Utils.write_json(self.cacheFile, dict)
        MBox.success("保存成功！")

        self.stringer_save_signal.emit(filterDict)

        self.lastMaterials = (
            Utils.getTableLibrarysName(data=dict.get("ringFrame"), column=6)
            | Utils.getTableLibrarysName(data=dict.get("stringedBar"), column=3)
            | Utils.getTableLibrarysName(data=dict.get("skin2"), column=0)
        )
        self.lastStringedBars = Utils.getTableLibrarysName(
            data=dict.get("ringFrame"), column=7
        ) | Utils.getTableLibrarysName(data=dict.get("stringedBar"), column=4)

    def updateUI(self, data):
        
        # 先将 厚度 和 起始终止厚度 禁用
        item = self.widgetDict["skin3"].item(0, 1)
        item.setFlags(item.flags() & ~Qt.ItemIsEnabled)
        item.setForeground(QColor(255, 255, 255, 128))  # 半透明
        self.widgetDict["skin3"].horizontalHeader().setStyleSheet(
            """
                                            QHeaderView::section:last { color: rgba(255, 255, 255, 0.5); }
                                        """
        )
        self.widgetDict["skin4"].clearRow(0)
        self.widgetDict["skin4"].setEnabled(False)
        
        if data:
            for row_data in data.get("rib_r") or []:
                self.widgetDict["stringedBar"].addRow(rowData=row_data)
            ringFrameData = (data.get("grid_set") or [[]]) + (
                data.get("grid_ring") or [[]]
            )
            grid_set = data.get("grid_set")
            grid_ring = data.get("grid_ring")
            if grid_set:
                for sublist in grid_set:
                    sublist = Utils.process_array(sublist, 7)
                    sublist.insert(5, "定位点")
            if grid_ring:
                for sublist in grid_ring:
                    sublist = Utils.process_array(sublist, 7)
                    sublist.insert(5, "环框")

            ringFrameData = [sublist for sublist in ringFrameData if sublist]
            for row_data in ringFrameData:
                self.widgetDict["ringFrame"].addRow(rowData=row_data)
            skin1 = [data.get("prop_start"), data.get("element_start")]
            skin2 = [data.get("shell_material"), data.get("shell_len")]
            skin3 = ["", ""]
            skin4 = ["", "", ""]
            if data.get("shell_thick_equal") == True:
                skin3 = ["均匀厚度", data.get("shell_thick")]
                item = self.widgetDict["skin3"].item(0, 1)
                item.setFlags(
                    item.flags()
                    | Qt.ItemIsEnabled
                    | Qt.ItemIsSelectable
                    | Qt.ItemIsEditable
                )
                item.setForeground(QColor(255, 255, 255))  # 不透明
                self.widgetDict["skin3"].horizontalHeader().setStyleSheet(
                    """
                                                    QHeaderView::section:last { color: white; }
                                                """
                )
                self.widgetDict["skin4"].clearRow(0)
                self.widgetDict["skin4"].setEnabled(False)
            elif data.get("shell_thick_equal") == False:
                skin3 = ["按周向设置", ""]
                skin4 = data.get("shell_thick") or []
                self.widgetDict["skin4"].setRowCount(0)
                for item in skin4:
                    self.widgetDict["skin4"].addRow(rowData=item)
                if len(skin4) == 0:
                    self.widgetDict["skin4"].addRow()
                item = self.widgetDict["skin3"].item(0, 1)
                item.setFlags(item.flags() & ~Qt.ItemIsEnabled)
                item.setForeground(QColor(255, 255, 255, 128))  # 半透明
                self.widgetDict["skin3"].horizontalHeader().setStyleSheet(
                    """
                                                    QHeaderView::section:last { color: rgba(255, 255, 255, 0.5); }
                                                """
                )
                self.widgetDict["skin4"].setEnabled(True)

            self.widgetDict["skin1"].fillRowData(row=0, rowData=skin1)
            self.widgetDict["skin2"].fillRowData(row=0, rowData=skin2)
            self.widgetDict["skin3"].fillRowData(row=0, rowData=skin3)

    def setTableFixeHeight(self, table):
        total_height = table.rowHeight(0)
        horizontal_header_height = table.horizontalHeader().height()
        table.setFixedHeight(total_height + horizontal_header_height)
        
    def skin_export(self):
        tableList = [self.widgetDict["skin1"],self.widgetDict["skin2"],self.widgetDict["skin3"],self.widgetDict["skin4"]]
        export_tables_to_single_csv(
            tables=tableList
        )

    def skin3_select_changed_signal(self, lastValue, value):
        item = self.widgetDict["skin3"].item(0, 1)
        if value == "均匀厚度":
            item.setFlags(
                item.flags()
                | Qt.ItemIsEnabled
                | Qt.ItemIsSelectable
                | Qt.ItemIsEditable
            )
            self.widgetDict["skin4"].setEnabled(False)
            item.setForeground(QColor(255, 255, 255))  # 不透明
            self.widgetDict["skin3"].horizontalHeader().setStyleSheet(
                """
                                                    QHeaderView::section:last { color: white; }
                                                """
            )

        elif value == "按周向设置":
            item.setFlags(item.flags() & ~Qt.ItemIsEnabled)
            item.setForeground(QColor(255, 255, 255, 128))  # 半透明
            self.widgetDict["skin4"].setEnabled(True)
            self.widgetDict["skin3"].horizontalHeader().setStyleSheet(
                """
                                                    QHeaderView::section:last { color: rgba(255, 255, 255, 0.5); }
                                                """
            )
        else:
            item.setFlags(item.flags() & ~Qt.ItemIsEnabled)
            item.setForeground(QColor(255, 255, 255, 128))  # 半透明
            self.widgetDict["skin4"].setEnabled(False)
            self.widgetDict["skin3"].horizontalHeader().setStyleSheet(
                """
                                                    QHeaderView::section:last { color: rgba(255, 255, 255, 0.5); }
                                                """
            )


# if __name__ == "__main__":
#     app = QApplication(sys.argv)
#     window = StringerDialog()
#     window.show()
#     sys.exit(app.exec_())
